package com.hyt.it.ogt.pj.service.impl;

import cn.hutool.core.map.MapBuilder;
import com.alibaba.fastjson.JSON;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.exception.exception.BusinessRequestException;
import com.hyt.it.ogt.common.config.GlobalConfig;
import com.hyt.it.ogt.common.utils.DateUtils;
import com.hyt.it.ogt.pj.enums.ProjectDownLoadStatusEnum;
import com.hyt.it.ogt.pj.feign.cloudefile.PushTaskClient;
import com.hyt.it.ogt.pj.feign.cloudefile.RecordClient;
import com.hyt.it.ogt.pj.mapper.ProjectMapper;
import com.hyt.it.ogt.pj.model.entity.Project;
import com.hyt.it.ogt.pj.model.entity.Student;
import com.hyt.it.ogt.pj.service.INewProjectService;
import com.hyt.it.ogt.pj.service.IStudentService;
import com.hyt.loginfo.model.User;
import com.hyt.model.cloudefile.apiparams.FileRecodeParam;
import com.hyt.model.cloudefile.apiparams.PushTaskParam;
import com.hyt.model.cloudefile.entity.CloudeFileProjectRecord;
import com.hyt.model.cloudefile.enums.*;
import com.hyt.progress.ProgressHolder;
import com.hyt.progress.constants.ProgressConstant;
import com.hyt.progress.service.ProgressManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 评卷项目表 服务实现类
 * </p>
 *
 * @author qiaozj
 * @since 2020-07-09
 */
@Service
public class NewProjectServiceImpl extends BaseServiceImpl<ProjectMapper, Project> implements INewProjectService {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${download.timeinterval:1}")
    private Integer downloadTimeinterval;
    @Resource
    private IStudentService studentService;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private PushTaskClient pushTaskClient;
    @Resource
    private RecordClient recordClient;
    @Resource
    GlobalConfig globalConfig;

    @Override
    public void projectDataDownload(String projectId, User user) throws Exception {
        checkProjectExist(projectId);
        // 获取文件下载记录下载中，则直接告诉客户下载洪
        if (checkCreatedAndUpdateProgress(projectId, FileTypeEnum.PJ_PROJECT_ALL_ZIP)) return;

        // 异步导出zip文件
        //新增校验任务
        PushTaskParam pushTaskParam = new PushTaskParam();
        pushTaskParam.setProjectId(projectId);
        //pushTaskParam.setFileUrl();
        pushTaskParam.setSystemType(SystemEnum.PJ.getSystemType());
        pushTaskParam.setOperateType(OperateTypeEnum.FILE_DOWNLOAD.getOperateType());
        pushTaskParam.setFileType(FileTypeEnum.PJ_PROJECT_ALL_ZIP.getFileType());
        pushTaskParam.setFileKey(JobKeyEnum.PJEXPORTJOB_PROJECTDATADOWNLOAD.getKey());
        pushTaskParam.setExecuteImmediately(Boolean.TRUE);
        pushTaskParam.setOfficeId(user.getOfficeid());
        pushTaskParam.setDeptId(user.getOrganizationid());
        pushTaskParam.setUserId(user.getId());
        setProgressInfo(pushTaskParam);
        ApiResponse<Boolean> response = pushTaskClient.pushTask(pushTaskParam);
        //任务处理失败
        if (null == response || !response.getData()) {
            BusinessRequestException.throwException(51150102, "任务处理失败");
        }
    }

    private static void setProgressInfo(PushTaskParam pushTaskParam) {
        Map<String, Object> progressKey = MapBuilder.<String, Object>create()
                .put(ProgressConstant.PROGRESS_KEY, ProgressHolder.get())
                .build();
        pushTaskParam.setDynamicAttr(progressKey);
        ProgressManager.getProgressId().ifPresent(pushTaskParam::setProgressId);
        ProgressManager.updateProgressCurrent(10, "开始任务");
    }

    @Override
    public void dkbProjectDataDownload(String projectId, User user) throws Exception {
        checkProjectExist(projectId);
        // 获取文件下载记录下载中，则直接告诉客户下载洪
        if (checkCreatedAndUpdateProgress(projectId, FileTypeEnum.PJ_DBK_PROJECT_ALL_ZIP)) return;
        // 异步导出zip文件
        //新增校验任务
        PushTaskParam pushTaskParam = new PushTaskParam();
        pushTaskParam.setProjectId(projectId);
        //pushTaskParam.setFileUrl();
        pushTaskParam.setSystemType(SystemEnum.PJ.getSystemType());
        pushTaskParam.setOperateType(OperateTypeEnum.FILE_DOWNLOAD.getOperateType());
        pushTaskParam.setFileType(FileTypeEnum.PJ_DBK_PROJECT_ALL_ZIP.getFileType());
        pushTaskParam.setFileKey(JobKeyEnum.PJEXPORTJOB_DKBPROJECTDATADOWNLOAD.getKey());
        pushTaskParam.setExecuteImmediately(Boolean.TRUE);
        pushTaskParam.setOfficeId(user.getOfficeid());
        pushTaskParam.setDeptId(user.getOrganizationid());
        pushTaskParam.setUserId(user.getId());
        setProgressInfo(pushTaskParam);
        ApiResponse<Boolean> response = pushTaskClient.pushTask(pushTaskParam);
        //任务处理失败
        if (null == response || response.getCode() != 20000) {
            BusinessRequestException.throwException(51150102, "任务处理失败");
        }
    }

    private void checkProjectExist(String projectId) {
        Project project = projectMapper.selectById(projectId);
        if (null == project) {
            BusinessRequestException.throwException(51150102, "项目不存在");
        }
    }

    @Override
    public void objectiveScoreDataDownload(String projectId, User user) throws Exception {
        checkProjectExist(projectId);
        // 获取文件下载记录下载中，则直接告诉客户下载洪
        if (checkCreatedAndUpdateProgress(projectId, FileTypeEnum.PJ_PROJECT_OBJECTIVE_SCORE)) return;

        // 异步导出zip文件
        PushTaskParam pushTaskParam = new PushTaskParam();
        pushTaskParam.setProjectId(projectId);
        pushTaskParam.setSystemType(SystemEnum.PJ.getSystemType());
        pushTaskParam.setOperateType(OperateTypeEnum.FILE_DOWNLOAD.getOperateType());
        pushTaskParam.setFileType(FileTypeEnum.PJ_PROJECT_OBJECTIVE_SCORE.getFileType());
        pushTaskParam.setFileKey(JobKeyEnum.PJEXPORTJOB_OBJECTIVESCOREDATADOWNLOAD.getKey());
        pushTaskParam.setExecuteImmediately(Boolean.TRUE);
        pushTaskParam.setOfficeId(user.getOfficeid());
        pushTaskParam.setDeptId(user.getOrganizationid());
        pushTaskParam.setUserId(user.getId());
        setProgressInfo(pushTaskParam);
        ApiResponse<Boolean> response = pushTaskClient.pushTask(pushTaskParam);
        //任务处理失败
        if (null == response || response.getCode() != 20000) {
            BusinessRequestException.throwException(51150302, "任务处理失败");
        }

    }

    private boolean checkCreatedAndUpdateProgress(String projectId, FileTypeEnum pjProjectObjectiveScore) {
        ApiResponse<Object> queryLastRecord = queryLastRecord(projectId, pjProjectObjectiveScore);
        if (reqSuccess(queryLastRecord)) {
            CloudeFileProjectRecord parse = parse(queryLastRecord);
            if (alreadyCreated(projectId, parse)) {
                ProgressManager.finish(parse.getFileUrl());
                return true;
            }
        }
        return false;
    }


    @Override
    public void dkbObjectiveScoreDataDownload(String projectId, User user) throws Exception {
        checkProjectExist(projectId);
        // 获取文件下载记录下载中，则直接告诉客户下载洪
        if (checkCreatedAndUpdateProgress(projectId, FileTypeEnum.PJ_DBK_PROJECT_OBJECTIVE_SCORE)) return;

        // 异步导出zip文件
        //新增校验任务
        PushTaskParam pushTaskParam = new PushTaskParam();
        pushTaskParam.setProjectId(projectId);
        pushTaskParam.setSystemType(SystemEnum.PJ.getSystemType());
        pushTaskParam.setOperateType(OperateTypeEnum.FILE_DOWNLOAD.getOperateType());
        pushTaskParam.setFileType(FileTypeEnum.PJ_DBK_PROJECT_OBJECTIVE_SCORE.getFileType());
        pushTaskParam.setFileKey(JobKeyEnum.PJEXPORTJOB_DKBOBJECTIVESCOREDATADOWNLOAD.getKey());
        pushTaskParam.setExecuteImmediately(Boolean.TRUE);
        pushTaskParam.setOfficeId(user.getOfficeid());
        pushTaskParam.setDeptId(user.getOrganizationid());
        pushTaskParam.setUserId(user.getId());
        setProgressInfo(pushTaskParam);
        ApiResponse<Boolean> response = pushTaskClient.pushTask(pushTaskParam);
        //发送任务处理失败
        if (null == response || response.getCode() != 20000) {
            BusinessRequestException.throwException(51150302, "任务处理失败");
        }

    }


    private String getApiBack(String projectId, ApiResponse<Object> apiResponse) {
        if (null == apiResponse.getData()) {
            return null;
        }
        String jsonData = JSON.toJSONString(apiResponse.getData());
        //取最后一个任务
        CloudeFileProjectRecord cloudeFileProjectRecord = JSON.parseObject(jsonData, CloudeFileProjectRecord.class);
        if (FileStatusEnum.PROCESSING.getStatus().equals(cloudeFileProjectRecord.getStatus())) {
            // 判断文件是不是已经距离导出时间1小时内
            LocalDateTime createLocationTime = cloudeFileProjectRecord.getCreateDate();
            Date createDate = DateUtils.asDate(createLocationTime);
            Date createDateOneHourAfter = DateUtils.afterHoursToNowDate(createDate, downloadTimeinterval);
            Date now = new Date();
            if (now.compareTo(createDateOneHourAfter) < 0) {
                return ProjectDownLoadStatusEnum.downloading.getStatus();
            }
            // 如果文件下载成功
        } else if (FileStatusEnum.SUCCESS.getStatus().equals(cloudeFileProjectRecord.getStatus())
                && StringUtils.isNotEmpty(cloudeFileProjectRecord.getFileUrl())) {
            // 获取下载记录的创建时间
            LocalDateTime recordCreateDate = cloudeFileProjectRecord.getCreateDate();
            // 获取项目下的考生最新的时间
            Student student = studentService.getLastOneStudentByProject(projectId);
            LocalDateTime studentCreateDate = student.getCreateDate();
            if (recordCreateDate.compareTo(studentCreateDate) > 0) {
                return cloudeFileProjectRecord.getFileUrl();
            }
        }
        return null;
    }

    private boolean alreadyCreated(String projectId, CloudeFileProjectRecord cloudeFileProjectRecord) {
        if (Objects.nonNull(cloudeFileProjectRecord) && FileStatusEnum.SUCCESS.getStatus().equals(cloudeFileProjectRecord.getStatus())
                && StringUtils.isNotEmpty(cloudeFileProjectRecord.getFileUrl())) {
            // 获取下载记录的创建时间
            LocalDateTime recordCreateDate = cloudeFileProjectRecord.getCreateDate();
            // 获取项目下的考生最新的时间
            Student student = studentService.getLastOneStudentByProject(projectId);
            LocalDateTime studentCreateDate = student.getCreateDate();
            if (recordCreateDate.compareTo(studentCreateDate) > 0) {
                return true;
            }
        }
        return false;
    }

    private static boolean reqSuccess(ApiResponse<Object> apiResponse) {
        if (apiResponse != null && apiResponse.getCode() == 20000) {
            return true;
        }
        return false;
    }

    private static CloudeFileProjectRecord parse(ApiResponse<Object> apiResponse) {
        String jsonData = JSON.toJSONString(apiResponse.getData());
        return JSON.parseObject(jsonData, CloudeFileProjectRecord.class);
    }

    private ApiResponse<Object> queryLastRecord(String projectId, FileTypeEnum fileTypeEnum) {
        FileRecodeParam fileRecodeParam = new FileRecodeParam();
        fileRecodeParam.setProjectId(projectId);
        fileRecodeParam.setSystemType(SystemEnum.PJ.getSystemType());
        fileRecodeParam.setFileType(fileTypeEnum.getFileType());
        return recordClient.queryLastFileRecode(fileRecodeParam);
    }


    private String getZipUrl(ApiResponse<Object> apiResponse) {
        if (null == apiResponse.getData()) {
            return null;
        }
        String jsonData = JSON.toJSONString(apiResponse.getData());
        CloudeFileProjectRecord cloudeFileProjectRecord = JSON.parseObject(jsonData, CloudeFileProjectRecord.class);
        if (FileStatusEnum.SUCCESS.getStatus().equals(cloudeFileProjectRecord.getStatus())
                && StringUtils.isNotEmpty(cloudeFileProjectRecord.getFileUrl())) {
            return cloudeFileProjectRecord.getFileUrl();

        }
        return null;

    }

}
